package com.probiz.estoresa.order.web.action;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.validation.BindException;
import org.springframework.web.servlet.ModelAndView;

import com.probiz.estore.Constants;
import com.probiz.estore.common.model.customer.Address;
import com.probiz.estore.common.model.customer.Customer;
import com.probiz.estore.common.model.order.CheckoutSession;
import com.probiz.estore.common.model.order.OrderAddress;
import com.probiz.estore.common.model.order.OrderPayment;
import com.probiz.estore.common.model.order.OrderPick;
import com.probiz.estore.common.model.order.OrderShipment;
import com.probiz.estore.common.model.order.OrderShipmentItem;
import com.probiz.estore.common.model.order.OrderSku;
import com.probiz.estore.common.model.order.SalesOrder;
import com.probiz.estore.common.model.other.Tag;
import com.probiz.estore.common.model.product.ProductSku;
import com.probiz.estore.common.model.system.PaymentMethod;
import com.probiz.estore.common.model.system.Region;
import com.probiz.estore.common.model.system.SelfCollectionCentre;
import com.probiz.estore.common.model.system.ShippingRate;
import com.probiz.estore.common.model.system.Wrap;
import com.probiz.estore.common.service.CheckoutService;
import com.probiz.estore.common.util.DateUtil;
import com.probiz.estore.core.controller.GenericStoreAdminController;
import com.probiz.estore.core.search.SearchCriteria;
import com.probiz.estore.core.util.StringUtil;
import com.probiz.estore.customer.service.CustomerManager;
import com.probiz.estore.exception.GiftCertificateStateException;
import com.probiz.estore.exception.OrderProccessFlowException;
import com.probiz.estore.exception.OutOfStockException;
import com.probiz.estore.exception.ShopPointConsumptionException;
import com.probiz.estore.order.OrderConstants;
import com.probiz.estore.order.model.OrderCancelModel;
import com.probiz.estore.order.model.OrderCompleteModel;
import com.probiz.estore.order.model.OrderSearchCriteria;
import com.probiz.estore.order.service.OrderProcessFlowManager;
import com.probiz.estore.order.service.OrderSkuManager;
import com.probiz.estore.order.service.SalesOrderManager;
import com.probiz.estore.other.service.TagManager;
import com.probiz.estore.product.service.ProductSkuManager;
import com.probiz.estore.system.service.PaymentMethodManager;
import com.probiz.estore.system.service.RegionManager;
import com.probiz.estore.system.service.SelfCollectionCentreManager;
import com.probiz.estore.system.service.ShippingMethodManager;
import com.probiz.estore.system.service.ShippingRateManager;
import com.probiz.estore.system.service.WrapManager;
import com.probiz.estore.webapp.util.RequestUtil;

public class SalesOrderController extends GenericStoreAdminController<SalesOrder> {
	
	private final static String SALES_ORDER_NO_SET_4PICK = "salesOrderNoSet4Pick";
	
	private SalesOrderManager salesOrderManager ;

	private CustomerManager customerManager ;

	private ShippingRateManager shippingRateManager ;

	private OrderProcessFlowManager orderProcessFlowManager ;

	private WrapManager wrapManager ;

	private TagManager tagManager ;
	
	private OrderSkuManager orderSkuManager;

	private PaymentMethodManager paymentMethodManager ;
	
	private ShippingMethodManager shippingMethodManager ;

	private RegionManager regionManager ;

	private SelfCollectionCentreManager selfCollectionCentreManager;

	private CheckoutService checkoutService;
	
	private ProductSkuManager productSkuManager;

	public void setWrapManager(WrapManager wrapManager) {
		this.wrapManager = wrapManager;
	}

	public void setOrderProcessFlowManager(OrderProcessFlowManager orderProcessFlowManager) {
		this.orderProcessFlowManager = orderProcessFlowManager;
	}

	public void setShippingMethodManager(ShippingMethodManager shippingMethodManager) {
		this.shippingMethodManager = shippingMethodManager;
	}

	public void setShippingRateManager(ShippingRateManager shippingRateManager) {
		this.shippingRateManager = shippingRateManager;
	}

	public void setSalesOrderManager(SalesOrderManager inMgr) {
		this.salesOrderManager = inMgr;
	}

	public void setRegionManager(RegionManager regionManager) {
		this.regionManager = regionManager;
	}

	public void setTagManager(TagManager tagManager) {
		this.tagManager = tagManager;
	}

	public void setOrderSkuManager(OrderSkuManager orderSkuManager) {
		this.orderSkuManager = orderSkuManager;
	}

	public void setCustomerManager(CustomerManager customerManager) {
		this.customerManager = customerManager;
	}

	public void setCheckoutService(CheckoutService checkoutService) {
		this.checkoutService = checkoutService;
	}

	public void setPaymentMethodManager(PaymentMethodManager paymentMethodManager) {
		this.paymentMethodManager = paymentMethodManager;
	}

	public void setSelfCollectionCentreManager(SelfCollectionCentreManager selfCollectionCentreManager) {
		this.selfCollectionCentreManager = selfCollectionCentreManager;
	}
	

	public void setProductSkuManager(ProductSkuManager productSkuManager) {
		this.productSkuManager = productSkuManager;
	}

	@Override
	protected String getEntityName(SalesOrder entity) {
		return entity.getSalesOrderName();
	}


	@Override
	protected void initController() throws Exception {
		mgr = salesOrderManager;
	}

	@Override
	protected void preSave(HttpServletRequest request, SalesOrder entity, BindException errors) {
	}

	public ModelAndView defaultAction(HttpServletRequest request, HttpServletResponse response) {
		ModelAndView mv = new ModelAndView("order/salesOrderList");
		mv.addObject("paymentMethodList", paymentMethodManager.getByPaymentMethodTypeStatus(PaymentMethod.PAYMENT_METHOD_TYPE_OFFLINE, Constants.STATUS_ACTIVE));
		mv.addObject("shippingMethodList", shippingMethodManager.findUnDeletedShippingMethods());
		return mv;
	}

	public ModelAndView search(HttpServletRequest request, HttpServletResponse response) {
		ModelAndView mv = new ModelAndView("order/include/salesOrderListBody");
		SearchCriteria searchCriteria = createSearchCriteria(request);
		OrderSearchCriteria orderSearchCriteria = new OrderSearchCriteria();
		try {
			// 绑定参数
			bind(request, orderSearchCriteria);
			List<SalesOrder> orderList = salesOrderManager.searchByCriteriaForController(orderSearchCriteria, searchCriteria);
			mv.addObject("orderList", orderList);
			mv.addObject("orderSearchCriteria", orderSearchCriteria);
		} catch (Exception e) {
			e.printStackTrace();
		}

		return mv;
	}

	/**
	 * 详细页展开
	 * 
	 * @param request
	 * @param response
	 * @return
	 * @throws Exception
	 */
	public ModelAndView showOrderItem(HttpServletRequest request, HttpServletResponse response) throws Exception {
		SalesOrder salesOrder = formBackingObject(request);
		ModelAndView mv = new ModelAndView("order/include/orderItemInList");
		mv.addObject("order", salesOrder);
		return mv;

	}
	
	/**
	 * 订单Tr
	 * 
	 * @param request
	 * @param response
	 * @return
	 * @throws Exception
	 */
	public ModelAndView showOrderTr(HttpServletRequest request, HttpServletResponse response) throws Exception {
		SalesOrder salesOrder = formBackingObject(request);
		ModelAndView mv = new ModelAndView("order/include/orderTrInList");
		mv.addObject("order", salesOrder);
		mv.addObject("fromReload", true);
		return mv;

	}
	
	/**
	 * 加入返回参数
	 * @param data
	 * @param salesOrder
	 * @param request
	 */
	private void buildReturnInfo(Map<String, Object> data, SalesOrder salesOrder, HttpServletRequest request) {
		data.put("salesOrderId", salesOrder.getSalesOrderId());
		data.put("orderNo", salesOrder.getOrderNo());
	}

	/**
	 * 确认订单
	 * 
	 * @param request
	 * @param response
	 * @return
	 * @throws Exception
	 */
	public ModelAndView confirmOrder(HttpServletRequest request, HttpServletResponse response) throws Exception {
		SalesOrder salesOrder = formBackingObject(request);
		Map<String, Object> data = new HashMap<String, Object>();
		try{
			orderProcessFlowManager.doConfirmOrder(salesOrder);
		}catch(OrderProccessFlowException e){
			data.put("errorMessage", e.getMessage());
		}
		buildReturnInfo(data, salesOrder, request);
		return getModelAndAjaxJsonView(data);
	}
	/**
	 * 显示订单收款面板
	 * @param request
	 * @param response
	 * @return
	 * @throws Exception
	 */
	public ModelAndView showPayPanel(HttpServletRequest request, HttpServletResponse response) throws Exception {
		SalesOrder salesOrder = formBackingObject(request);
		ModelAndView mv = new ModelAndView("order/orderPayPanel");
		mv.addObject("order", salesOrder);
		mv.addObject("onlinePaymentMethodList", paymentMethodManager.getByPaymentMethodTypeStatus(PaymentMethod.PAYMENT_METHOD_TYPE_ONLINE, Constants.STATUS_ACTIVE));
		return mv;
	}
	/**
	 * 订单收款
	 * 
	 * @param request
	 * @param response
	 * @return
	 * @throws Exception
	 */
	public ModelAndView payOrder(HttpServletRequest request, HttpServletResponse response) throws Exception {
		SalesOrder salesOrder = formBackingObject(request);
		OrderPayment orderPayment = new OrderPayment();
		bind(request, orderPayment);
		
		//设置accountInfo
		if(OrderConstants.PAYMENT_METHOD_BANK.equals(orderPayment.getPaymentMethodId())){
			orderPayment.setAccountInfo(request.getParameter("accountInfoBankTransfer"));
		}else if(OrderConstants.PAYMENT_METHOD_POSTAL.equals(orderPayment.getPaymentMethodId())){
			orderPayment.setAccountInfo(request.getParameter("accountInfoPostOffice"));
		}
		//设置网关名称
		if(!OrderConstants.PAYMENT_METHOD_ONLINE.equals(orderPayment.getPaymentMethodId())){
			orderPayment.setPaymentGatewayName(null);
		}
		//设置PaymentType
		if(!OrderConstants.PAYMENT_METHOD_OFFLINE.equals(orderPayment.getPaymentMethodId())){
			orderPayment.setPaymentType(null);
		}
		Map<String, Object> data = new HashMap<String, Object>();
		try{
			orderProcessFlowManager.doPayOrder(salesOrder,orderPayment);
		}catch(OrderProccessFlowException e){
			data.put("errorMessage", e.getMessage());
		}
		buildReturnInfo(data, salesOrder, request);
		return getModelAndAjaxJsonView(data);
	}
	
	/**
	 * 显示订单退款面板
	 * @param request
	 * @param response
	 * @return
	 * @throws Exception
	 */
	public ModelAndView showRefundPanel(HttpServletRequest request, HttpServletResponse response) throws Exception {
		SalesOrder salesOrder = formBackingObject(request);
		ModelAndView mv = new ModelAndView("order/orderRefundPanel");
		mv.addObject("order", salesOrder);
		mv.addObject("onlinePaymentMethodList", paymentMethodManager.getByPaymentMethodTypeStatus(PaymentMethod.PAYMENT_METHOD_TYPE_ONLINE, Constants.STATUS_ACTIVE));
		return mv;
	}
	
	/**
	 * 订单退款
	 * @param request
	 * @param response
	 * @return
	 * @throws Exception
	 */
	public ModelAndView refundOrder(HttpServletRequest request, HttpServletResponse response) throws Exception {
		SalesOrder salesOrder = formBackingObject(request);
		OrderPayment orderPayment = new OrderPayment();
		bind(request, orderPayment);
		
		//设置accountInfo
		if(OrderConstants.PAYMENT_METHOD_BANK.equals(orderPayment.getPaymentMethodId())){
			orderPayment.setAccountInfo(request.getParameter("accountInfoBankTransfer"));
		}else if(OrderConstants.PAYMENT_METHOD_POSTAL.equals(orderPayment.getPaymentMethodId())){
			orderPayment.setAccountInfo(request.getParameter("accountInfoPostOffice"));
		}
		//设置网关名称
		if(!OrderConstants.PAYMENT_METHOD_ONLINE.equals(orderPayment.getPaymentMethodId())){
			orderPayment.setPaymentGatewayName(null);
		}
		//设置PaymentType
		if(!OrderConstants.PAYMENT_METHOD_OFFLINE.equals(orderPayment.getPaymentMethodId())){
			orderPayment.setPaymentType(null);
		}
		Map<String, Object> data = new HashMap<String, Object>();
		try{
			orderProcessFlowManager.doRefundOrder(salesOrder,orderPayment);
		}catch(OrderProccessFlowException e){
			data.put("errorMessage", e.getMessage());
		}
		buildReturnInfo(data, salesOrder, request);
		return getModelAndAjaxJsonView(data);
	}
	
	/**
	 * 显示订单发货面板
	 * @param request
	 * @param response
	 * @return
	 * @throws Exception
	 */
	public ModelAndView showShipPanel(HttpServletRequest request, HttpServletResponse response) throws Exception {
		SalesOrder salesOrder = formBackingObject(request);
		ModelAndView mv = new ModelAndView("order/orderShipPanel");
		mv.addObject("order", salesOrder);
		if(null != salesOrder.getOrderAddress()){
			List<ShippingRate> shippingRateList = shippingRateManager.getDifferentShipMethodRatesByRegionId(null, salesOrder.getOrderAddress().getRegionId());
			mv.addObject("shippingRateList", shippingRateList);
		}
		if(null != salesOrder.getOrderAddress()){
			List<SelfCollectionCentre> selfCollectionCentreList =  selfCollectionCentreManager.getSelfCollectionCentreListByRegionId(salesOrder.getOrderAddress().getRegionId());
			mv.addObject("selfCollectionCentreList", selfCollectionCentreList);
		}
		return mv;
	}
	/**
	 * 订单发货
	 * @param request
	 * @param response
	 * @return
	 * @throws Exception
	 */
	public ModelAndView shipOrder(HttpServletRequest request, HttpServletResponse response) {
		SalesOrder salesOrder = formBackingObject(request);
		
		Map<String, Object> data = new HashMap<String, Object>();
		try{
			orderProcessFlowManager.doShipOrder(salesOrder,buildOrderShipmentModelForShip(request));
		}catch(OrderProccessFlowException e){
			data.put("errorMessage", e.getMessage());
		} catch (Exception e) {
			e.printStackTrace();
		}
		buildReturnInfo(data, salesOrder, request);
		return getModelAndAjaxJsonView(data);
	}
	
	/**
	 * 显示订单退货面板
	 * @param request
	 * @param response
	 * @return
	 * @throws Exception
	 */
	public ModelAndView showReturnPanel(HttpServletRequest request, HttpServletResponse response) throws Exception {
		SalesOrder salesOrder = formBackingObject(request);
		ModelAndView mv = new ModelAndView("order/orderReturnPanel");
		mv.addObject("order", salesOrder);
		if(null != salesOrder.getOrderAddress()){
			List<ShippingRate> shippingRateList = shippingRateManager.getDifferentShipMethodRatesByRegionId(null, salesOrder.getOrderAddress().getRegionId());
			mv.addObject("shippingRateList", shippingRateList);
		}
		if(null != salesOrder.getOrderAddress()){
			List<SelfCollectionCentre> selfCollectionCentreList =  selfCollectionCentreManager.getSelfCollectionCentreListByRegionId(salesOrder.getOrderAddress().getRegionId());
			mv.addObject("selfCollectionCentreList", selfCollectionCentreList);
		}
		return mv;
	}
	/**
	 * 订单退货
	 * @param request
	 * @param response
	 * @return
	 * @throws Exception
	 */
	public ModelAndView returnOrder(HttpServletRequest request, HttpServletResponse response) throws Exception {
		SalesOrder salesOrder = formBackingObject(request);
		
		Map<String, Object> data = new HashMap<String, Object>();
		try{
			orderProcessFlowManager.doReturnOrder(salesOrder,buildOrderShipmentModelForShip(request));
		}catch(OrderProccessFlowException e){
			data.put("errorMessage", e.getMessage());
		}catch(Exception e){
			e.printStackTrace();
		}
		buildReturnInfo(data, salesOrder, request);
		return getModelAndAjaxJsonView(data);
	}
	/**
	 * 显示面板的地区修改
	 * @param request
	 * @param response
	 * @return
	 */
	public ModelAndView renderPanelRegionModify(HttpServletRequest request, HttpServletResponse response){
		ModelAndView mv = new ModelAndView("order/include/orderPanel4RegionModify");
		Integer regionId = RequestUtil.getInteger(request, "regionId");
		mv.addObject("regionId", regionId);
		return mv;
	}
	/**
	 * 显示面板的地区县市
	 * @param request
	 * @param response
	 * @return
	 */
	public ModelAndView renderPanelRegionShow(HttpServletRequest request, HttpServletResponse response){
		ModelAndView mv = new ModelAndView("order/include/orderPanel4RegionShow");
		Integer regionId = RequestUtil.getInteger(request, "regionId");
		Region region = regionManager.getById(regionId);
		mv.addObject("regionId",regionId);
		mv.addObject("regionFullName",region.getFullName());
		return mv;
	}
	/**
	 * 加载配送方式
	 * @param request
	 * @param response
	 * @return
	 */
	public ModelAndView renderDeliveryType(HttpServletRequest request, HttpServletResponse response){
		SalesOrder salesOrder = formBackingObject(request);
		ModelAndView mv = new ModelAndView("order/include/orderShipReturnPanel4DeliveryTypeDesc");
		mv.addObject("order", salesOrder);
		Integer regionId = RequestUtil.getInteger(request, "regionId");
		if(null != salesOrder.getOrderAddress()){
			List<ShippingRate> shippingRateList = shippingRateManager.getDifferentShipMethodRatesByRegionId(null, salesOrder.getOrderAddress().getRegionId());
			mv.addObject("shippingRateList", shippingRateList);
		}
		if(null != salesOrder.getOrderAddress()){
			List<SelfCollectionCentre> selfCollectionCentreList =  selfCollectionCentreManager.getSelfCollectionCentreListByRegionId(regionId);
			mv.addObject("selfCollectionCentreList", selfCollectionCentreList);
		}
		return mv;
	}
	/**
	 * 构造发退货单
	 * @param request
	 * @param response
	 * @return
	 * @throws Exception
	 */
	private OrderShipment buildOrderShipmentModelForShip(HttpServletRequest request) {
		OrderShipment orderShipment = new OrderShipment();
		OrderAddress orderAddress = new OrderAddress();
		try {
			bind(request, orderShipment);
		} catch (Exception e) {
			e.printStackTrace();
		}
		Integer deliveryKind = RequestUtil.getInteger(request, "deliveryKind");
		if(null != deliveryKind){
			if(!OrderConstants.DELIVERY_KIND_CARRIER.equals(deliveryKind.shortValue())){
				orderShipment.setShippingMethodId(null);
			}else{
				orderShipment.setSelfCollectionCentreId(null);
			}
		}
		try { 
			bindAndValidate(request, orderAddress);
		} catch (Exception e) {
			e.printStackTrace();
		}
		orderShipment.setShippingAddress(orderAddress);
		String[] orderSkuIds = RequestUtil.getParameterValuesNullSafe(request, "orderSkuId");
		String[] shipQuantities = RequestUtil.getParameterValuesNullSafe(request, "shipQuantity");
		String[] incomingQuantities = RequestUtil.getParameterValuesNullSafe(request, "incomingQuantity");
		for(int i=0; i< orderSkuIds.length; i++){
			if(Integer.valueOf(shipQuantities[i]) != 0){
				//必须有数量才加入
				OrderShipmentItem orderShipmentItem = new OrderShipmentItem();
				OrderSku orderSku = orderSkuManager.getById(Integer.valueOf(orderSkuIds[i]));
				orderShipmentItem.setOrderSku(orderSku);
				orderShipmentItem.setDeliveryQuantity(Integer.valueOf(shipQuantities[i]));
				if(!ArrayUtils.isEmpty(incomingQuantities)){
					orderShipmentItem.setIncomingQuantity(Integer.valueOf(incomingQuantities[i]));
				}
				orderShipment.getOrderShipmentItems().add(orderShipmentItem);
			}
		}
		if(StringUtils.isNotBlank(orderShipment.getReturnReason())){
			orderShipment.setReturnReason(RequestUtil.getParameterNullSafe(request, "returnReasonPre")+","+orderShipment.getReturnReason());
		}else{
			orderShipment.setReturnReason(RequestUtil.getParameterNullSafe(request, "returnReasonPre"));
		}
		return orderShipment;
	}
	
	
	/**
	 * 完成订单
	 * 
	 * @param request
	 * @param response
	 * @return
	 * @throws Exception
	 */
	public ModelAndView completeOrder(HttpServletRequest request, HttpServletResponse response) throws Exception {
		SalesOrder salesOrder = formBackingObject(request);
		OrderCompleteModel completeModel = new OrderCompleteModel();
		this.bindOnly(request, completeModel);
		Map<String, Object> data = new HashMap<String, Object>();
		try{
			orderProcessFlowManager.doCompleteOrder(salesOrder,completeModel);
		}catch(OrderProccessFlowException e){
			data.put("errorMessage", e.getMessage());
		}
		buildReturnInfo(data, salesOrder, request);
		return getModelAndAjaxJsonView(data);
	}
	
	/**
	 * 显示订单完成面板
	 * @param request
	 * @param response
	 * @return
	 * @throws Exception
	 */
	public ModelAndView showCompletePanel(HttpServletRequest request, HttpServletResponse response) throws Exception {
		SalesOrder salesOrder = formBackingObject(request);
		ModelAndView mv = new ModelAndView("order/orderCompletePanel");
		mv.addObject("order", salesOrder);
		return mv;
	}
	/**
	 * 显示订单作废面板
	 * @param request
	 * @param response
	 * @return
	 * @throws Exception
	 */
	public ModelAndView showCancelPanel(HttpServletRequest request, HttpServletResponse response) throws Exception {
		SalesOrder salesOrder = formBackingObject(request);
		ModelAndView mv = new ModelAndView("order/orderCancelPanel");
		mv.addObject("order", salesOrder);
		return mv;
	}
	
	/**
	 * 管理员作废订单
	 * 
	 * @param request
	 * @param response
	 * @return
	 * @throws Exception
	 */
	public ModelAndView cancelOrderByAdmin(HttpServletRequest request, HttpServletResponse response) throws Exception {
		SalesOrder salesOrder = formBackingObject(request);
		salesOrder.setCancelReason(RequestUtil.getParameterNullSafe(request, "cancelReason"));
		OrderCancelModel cancelModel = new OrderCancelModel();
		this.bindOnly(request, cancelModel);
		Map<String, Object> data = new HashMap<String, Object>();
		try{
			orderProcessFlowManager.doCancelOrderByAdmin(salesOrder,cancelModel);
		}catch(OrderProccessFlowException e){
			data.put("errorMessage", e.getMessage());
		}
		buildReturnInfo(data, salesOrder, request);
		return getModelAndAjaxJsonView(data);
	}
	
	/**
	 * 保存订单备注
	 * @param request
	 * @param response
	 * @return
	 */
	public ModelAndView saveMemo(HttpServletRequest request, HttpServletResponse response){
		SalesOrder salesOrder = formBackingObject(request);
		salesOrder.setMemo(request.getParameter("memo"));
		salesOrderManager.save(salesOrder);
		Map<String, Object> data = new HashMap<String, Object>();
		return getModelAndAjaxJsonView(data);
	}
	
	
	/**
	 * 打印订单
	 * 
	 * @param request
	 * @param response
	 * @return
	 */
	public ModelAndView printOrderList(HttpServletRequest request, HttpServletResponse response) {
		List<SalesOrder> salesOrderList = new ArrayList<SalesOrder>();
		String[] ids = request.getParameterValues("multiIds");
		if (ids != null && ids.length > 0) {
			for (String id: ids) {
				SalesOrder order=salesOrderManager.getById(Integer.valueOf(id));
				salesOrderList.add(order);
			}
			
		}
		ModelAndView mv = new ModelAndView("order/print/salesOrderPrintList");
		mv.addObject("salesOrderList", salesOrderList);
		return mv;
	}
	
	/**
	 * 显示订单备货面板
	 * @param request
	 * @param response
	 * @return
	 * @throws Exception
	 */
	public ModelAndView showPickPanel(HttpServletRequest request, HttpServletResponse response) throws Exception {
		ModelAndView mv = new ModelAndView("order/orderPickPanel");
		Set<String> salesOrderNoSet4Pick = getSalesOrderNoSet4Pick(request);
		mv.addObject("salesOrderNoSet4Pick", salesOrderNoSet4Pick);
		return mv;
	}
	/**
	 * 获得当前备货任务列表
	 * @param request
	 * @return
	 */
	private Set<String> getSalesOrderNoSet4Pick(HttpServletRequest request) {
		Set<String> salesOrderNoSet4Pick;
		if(request.getSession().getAttribute(SALES_ORDER_NO_SET_4PICK)!=null){
			salesOrderNoSet4Pick = (Set<String>)request.getSession().getAttribute(SALES_ORDER_NO_SET_4PICK);
		}else{
			salesOrderNoSet4Pick = new LinkedHashSet<String>();
		}
		return salesOrderNoSet4Pick;
	}
	
	/**
	 * 订单备货面板-移除多个订单
	 * @param request
	 * @param response
	 * @return
	 * @throws Exception
	 */
	public ModelAndView removeOrderNo4PickPanel(HttpServletRequest request, HttpServletResponse response) throws Exception {
		Set<String> salesOrderNoSet4Pick = getSalesOrderNoSet4Pick(request);
		String[] orderNos = request.getParameterValues("orderNo4Pick");
		if(!ArrayUtils.isEmpty(orderNos)){
			for(String orderNo:orderNos){
				salesOrderNoSet4Pick.remove(orderNo);
			}
		}
		request.getSession().setAttribute(SALES_ORDER_NO_SET_4PICK, salesOrderNoSet4Pick);
		Map<String, Object> data = new HashMap<String, Object>();
		return getModelAndAjaxJsonView(data);
	}
	
	/**
	 * 订单备货面板-移除全部
	 * @param request
	 * @param response
	 * @return
	 * @throws Exception
	 */
	public ModelAndView removeAllOrderNo4PickPanel(HttpServletRequest request, HttpServletResponse response) throws Exception {
		request.getSession().setAttribute(SALES_ORDER_NO_SET_4PICK, null);
		Map<String, Object> data = new HashMap<String, Object>();
		return getModelAndAjaxJsonView(data);
	}
	
	/**
	 * 订单备货面板-添加备货
	 * @param request
	 * @param response
	 * @return
	 * @throws Exception
	 */
	public ModelAndView addOrderNo4PickPanel(HttpServletRequest request, HttpServletResponse response) throws Exception {
		Set<String> salesOrderNoSet4Pick = getSalesOrderNoSet4Pick(request);
		String[] ids = request.getParameterValues("multiIds");
		List<String> failOrderList = new ArrayList<String>();
		if (ids != null && ids.length > 0) {
			for (String id: ids) {
				
				SalesOrder salesOrder=salesOrderManager.getById(Integer.valueOf(id));
				if(OrderConstants.ORDER_STATUS_CONFIRMED.equals(salesOrder.getOrderStatus()) || OrderConstants.ORDER_STATUS_HANDLING.equals(salesOrder.getOrderStatus())){
					salesOrderNoSet4Pick.add(salesOrder.getOrderNo());
				}else{
					failOrderList.add(salesOrder.getOrderNo());
				}
			}
			
		}
		Map<String, Object> data = new HashMap<String, Object>();
		if(failOrderList.size() != 0){
			//处于非处理中状态（待确认、已完成和作废）的订单不能添加至备货单
			String failOrderNos = StringUtil.arrayToString(failOrderList.toArray(new String[0]), ",");
			data.put("message", getMessage("salesOrder.pickPanel.addOrderNos.success2",new Object[]{failOrderNos}));
		}else{
			data.put("message", getMessage("salesOrder.pickPanel.addOrderNos.success"));
		}
		request.getSession().setAttribute(SALES_ORDER_NO_SET_4PICK, salesOrderNoSet4Pick);
		return getModelAndAjaxJsonView(data);
	}

	
	/**
	 * 生成备货单
	 * 
	 * @param request
	 * @param response
	 * @return
	 * @throws Exception
	 */
	public ModelAndView pickOrder(HttpServletRequest request, HttpServletResponse response) throws Exception {
		SalesOrder salesOrder = formBackingObject(request);
		Map<String, Object> data = new HashMap<String, Object>();
		try{
			OrderPick orderPick = orderProcessFlowManager.doPickOrder(this.getSalesOrderNoSet4Pick(request));
			request.getSession().setAttribute(SALES_ORDER_NO_SET_4PICK, null);
			if(orderPick.getOrderPickId() == null){
				//没有可备货的商品
				data.put("failMessage", getMessage("salesOrder.pickPanel.pickOrder.notGen")); 
			}else if(orderPick.getSuccessOrderList().size() == 0){
				//没有订单可以备货
				data.put("failMessage", getMessage("salesOrder.pickPanel.pickOrder.fail"));
			}else if(orderPick.getFailOrderList().size() != 0){
				//处于非处理中状态（待确认、已完成和作废）的订单不能添加至备货单
				String failOrderNos = StringUtil.arrayToString(orderPick.getFailOrderList().toArray(new String[0]), ",");
				data.put("message", getMessage("salesOrder.pickPanel.pickOrder.success2",new Object[]{failOrderNos}));
			}else{
				data.put("message", getMessage("salesOrder.pickPanel.pickOrder.success"));
			}
		}catch(OrderProccessFlowException e){
			data.put("errorMessage", e.getMessage());
		}
		buildReturnInfo(data, salesOrder, request);
		return getModelAndAjaxJsonView(data);
	}
	
	
	/**
	 * 添加订单
	 * 
	 * @param request
	 * @param response
	 * @return
	 * @throws Exception
	 */
	public ModelAndView addSalesOrder(HttpServletRequest request, HttpServletResponse response) throws Exception {
		ModelAndView mv = new ModelAndView("order/orderAddPanel");
		return mv;
		
	}
	/**
	 * 订单添加面板-加载客户详细信息
	 * @param request
	 * @param response
	 * @return
	 * @throws Exception
	 */
	public ModelAndView loadCustomerDetail4AddPanel(HttpServletRequest request, HttpServletResponse response) throws Exception {
		Integer customerId = RequestUtil.getInteger(request, "customerId");
		Customer customer = customerManager.getByAppUserId(customerId);
		ModelAndView mv = new ModelAndView("order/include/orderAddPanel4CustomerDetail");
		mv.addObject("customer", customer);
		return mv;
		
	}
	/**
	 * 订单添加面板-加载订单详细信息
	 * @param request
	 * @param response
	 * @return
	 * @throws Exception
	 */
	public ModelAndView loadOrderInfo4AddPanel(HttpServletRequest request, HttpServletResponse response) throws Exception {
		ModelAndView mv = new ModelAndView("order/include/orderAddPanel4OrderInfo");
		//检查是否需要商品
		mv.addObject("isProductRequired", isProductRequired(request));
		//检查是否虚拟发货地址
		mv.addObject("isShippingRequired", isShippingRequired(request));
		Integer customerId = RequestUtil.getInteger(request, "customerId");
		if(null != customerId){
			Customer customer = customerManager.getByAppUserId(customerId);
			mv.addObject("address", customer.getDefaultAddress());
		}
		List<Wrap> wrapList = wrapManager.listAll();
		mv.addObject("wrapList", wrapList);
		addPayAndShipData(mv);
		return mv;
		
	}
	/**
	 * 添加支付配送基础数据
	 * @param mv
	 */
	private void addPayAndShipData(ModelAndView mv) {
		// 读取系统默认的支付信息
		List<PaymentMethod> paymentMethodList = paymentMethodManager.getByPaymentMethodTypeStatus(PaymentMethod.PAYMENT_METHOD_TYPE_OFFLINE, Constants.STATUS_ACTIVE);
		mv.addObject("paymentMethodList", paymentMethodList);
		
		// 提货时间列表
		List<Date> selfCollectDateList = new ArrayList();
		Date now = new Date();
		selfCollectDateList.add(DateUtil.getAddDay(now, 0));
		selfCollectDateList.add(DateUtil.getAddDay(now, 1));
		selfCollectDateList.add(DateUtil.getAddDay(now, 2));
		selfCollectDateList.add(DateUtil.getAddDay(now, 3));
		selfCollectDateList.add(DateUtil.getAddDay(now, 4));
		selfCollectDateList.add(DateUtil.getAddDay(now, 5));
		selfCollectDateList.add(DateUtil.getAddDay(now, 6));
		mv.addObject("selfCollectDateList", selfCollectDateList);
	}
	
	/**
	 * 订单添加面板-加载收货信息与支付配送信息
	 * @param request
	 * @param response
	 * @return
	 * @throws Exception
	 */
	public ModelAndView loadConsigneeAndPayShipMethodDiv4AddPanel(HttpServletRequest request, HttpServletResponse response) throws Exception {
		ModelAndView mv = new ModelAndView("order/include/orderAddPanel4ConsigneeAndPayShipMethod");
		
		//检查是否需要商品
		mv.addObject("isProductRequired", isProductRequired(request));
		//检查是否虚拟发货地址
		mv.addObject("isShippingRequired", isShippingRequired(request));
		Integer customerId = RequestUtil.getInteger(request, "customerId");
		
		//是否重新加载地址
		String loadAddressFlag = request.getParameter("loadAddressFlag");
		if(StringUtils.isNotBlank(loadAddressFlag)){
			//case：重新选择了客户，则订单收货地址为客户默认发货地址
			if(null != customerId){
				Customer customer = customerManager.getByAppUserId(customerId);
				mv.addObject("address", customer.getDefaultAddress());
			}
		}else{
			//case:没有重新选择客户，则将页面的客户填写的信息重新返回
			Address address = new Address();
			address.setFirstname(request.getParameter("name"));
			address.setEmail(request.getParameter("email"));
			address.setAddress(request.getParameter("address"));
			address.setTelephone(request.getParameter("telephone"));
			address.setZip(request.getParameter("postalcode"));
			address.setRegionId(RequestUtil.getInteger(request, "regionId"));
			address.setRegionFullName(request.getParameter("regionFullName"));
			mv.addObject("address", address);
		}
		addPayAndShipData(mv);
		return mv;
		
	}
	
	/**
	 * 订单添加面板-加载支付与配送方式
	 * @param request
	 * @param response
	 * @return
	 * @throws Exception
	 */
	public ModelAndView loadPayShipMethodDiv4AddPanel(HttpServletRequest request, HttpServletResponse response) throws Exception {
		ModelAndView mv;
		if(isProductRequired(request)){
			mv = new ModelAndView("order/include/orderAddPanel4PayAndShipMethodNeedProduct");
		}else{
			if(isShippingRequired(request)){
				mv = new ModelAndView("order/include/orderAddPanel4PayAndShipMethod");
				Integer regionId = RequestUtil.getInteger(request, "regionId");
				mv.addObject("regionId", regionId);
			}else{
				mv = new ModelAndView("order/include/orderAddPanel4PayAndVirtualShipMethod");
			}
		}
		addPayAndShipData(mv);
		return mv;
		
	}
	
	/**
	 * 订单添加面板-加载配送方式
	 * @param request
	 * @param response
	 * @return
	 * @throws Exception
	 */
	public ModelAndView loadShippingMethod4AddPanel(HttpServletRequest request, HttpServletResponse response) throws Exception {
		ModelAndView mv = new ModelAndView("order/include/orderAddPanel4ShippingMethod");
		PaymentMethod paymentMethod = paymentMethodManager.getById(RequestUtil.getInteger(request, "paymentMethodId"));
		Integer regionId = RequestUtil.getInteger(request, "regionId");
		List<ShippingRate> shippingRateList = checkoutService.getRegionShippingRates(Constants.FLAG_TRUE.equals(paymentMethod.getIscod())?true:false, regionId);
		mv.addObject("shippingRateList", shippingRateList);
		return mv;
		
	}
	/**
	 * 订单添加面板-加载自提方式
	 * @param request
	 * @param response
	 * @return
	 * @throws Exception
	 */
	public ModelAndView loadSelfCollectionCentre4AddPanel(HttpServletRequest request, HttpServletResponse response) throws Exception {
		ModelAndView mv = new ModelAndView("order/include/orderAddPanel4SelfCollectionCentre");
		Integer regionId = RequestUtil.getInteger(request, "regionId");
		List<SelfCollectionCentre> selfCollectionCentreList =  selfCollectionCentreManager.getSelfCollectionCentreListByRegionId(regionId);
		mv.addObject("selfCollectionCentreList", selfCollectionCentreList);
		return mv;
		
	}
	
	/**
	 * 订单添加预览面板
	 * @param request
	 * @param response
	 * @return
	 * @throws Exception
	 */
	public ModelAndView showAddPreviewPanel(HttpServletRequest request, HttpServletResponse response) throws Exception {
		ModelAndView mv = new ModelAndView("order/orderAddPanel4Preview");
		CheckoutSession checkoutSession = orderProcessFlowManager.buildCheckoutSession4Admin(request);
		mv.addObject("checkoutSession", checkoutSession);
		return mv;
	}
	/**
	 * 后台最终添加订单
	 * @param request
	 * @param response
	 * @return
	 * @throws Exception
	 */
	public ModelAndView addOrder(HttpServletRequest request, HttpServletResponse response) throws Exception {
		Map<String, Object> data = new HashMap<String, Object>();
		CheckoutSession checkoutSession = orderProcessFlowManager.buildCheckoutSession4Admin(request);
		try {
			//总金额不能超过8位
			if (checkoutSession.getShoppingcart().getTotal().compareTo(new BigDecimal("99999999"))==1) {
				throw new IllegalStateException(getMessage("checkout.detail.shoppoint.error"));
			}
			
			SalesOrder salesOrder = checkoutService.doPlaceOrder(checkoutSession);
			data.put("orderNo", salesOrder.getOrderNo());
		} catch (OutOfStockException e) {
			data.put("error", e.getMessage());
		} catch (GiftCertificateStateException e) {
			data.put("error", e.getMessage()); 
		} catch (ShopPointConsumptionException e) {
			data.put("error", e.getMessage()); 
		} catch (RuntimeException e) {
			data.put("error", e.getMessage());
			e.printStackTrace();
		}
		return getModelAndAjaxJsonView(data);
	}
	
	/**
	 * 后台最终添加订单成功
	 * @param request
	 * @param response
	 * @return
	 * @throws Exception
	 */
	public ModelAndView addOrderSuccess(HttpServletRequest request, HttpServletResponse response){
		ModelAndView mv = new ModelAndView("order/orderAddPanel");
		this.saveMessage(request, getMessage("checkout.addOrder.succ",	new Object[] { request.getParameter("orderNo") }));
		return mv;
	}
	
	

	/**
	 * 显示订单编辑面板
	 * 
	 * @param request
	 * @param response
	 * @return
	 * @throws Exception
	 */
	public ModelAndView edit(HttpServletRequest request, HttpServletResponse response) throws Exception {
		ModelAndView mv = new ModelAndView("order/orderEditPanel");
		SalesOrder salesOrder = formBackingObject(request);
		mv.addObject("order", salesOrder);
		mv.addObject("address", salesOrder.getOrderAddress());
		mv.addObject("isShippingRequired", salesOrder.isShippingRequired());
		List<Wrap> wrapList = wrapManager.listAll();
		mv.addObject("wrapList", wrapList);
		addPayAndShipData(mv);
		return mv;
	}
	
	
	/**
	 * 订单修改面板-加载订单详细信息
	 * @param request
	 * @param response
	 * @return
	 * @throws Exception
	 */
	public ModelAndView loadOrderInfo4EditPanel(HttpServletRequest request, HttpServletResponse response) throws Exception {
		ModelAndView mv = new ModelAndView("order/include/orderEditPanel4OrderInfo");
		//检查是否需要商品
		mv.addObject("isProductRequired", isProductRequired(request));
		//检查是否虚拟发货地址
		mv.addObject("isShippingRequired", isShippingRequired(request));
		SalesOrder salesOrder = formBackingObject(request);
		//设置订单和地区id变量
		mv.addObject("address", salesOrder.getOrderAddress());
		mv.addObject("order", salesOrder);
		mv.addObject("regionId", salesOrder.getOrderAddress().getRegionId());
		
		List<Wrap> wrapList = wrapManager.listAll();
		mv.addObject("wrapList", wrapList);
		addPayAndShipData(mv);
		return mv;
		
	}
	
	
	/**
	 * 订单编辑面板-加载收货信息与支付配送信息
	 * @param request
	 * @param response
	 * @return
	 * @throws Exception
	 */
	public ModelAndView loadConsigneeAndPayShipMethodDiv4EditPanel(HttpServletRequest request, HttpServletResponse response) throws Exception {
		ModelAndView mv = new ModelAndView("order/include/orderEditPanel4ConsigneeAndPayShipMethod");
		SalesOrder salesOrder = formBackingObject(request);
		//检查是否需要商品
		mv.addObject("isProductRequired", isProductRequired(request));
		//检查是否虚拟发货地址
		mv.addObject("isShippingRequired", isShippingRequired(request));
		
		//设置订单和地区id变量
		mv.addObject("address", salesOrder.getOrderAddress());
		mv.addObject("order", salesOrder);
		mv.addObject("regionId", salesOrder.getOrderAddress().getRegionId());
		
		addPayAndShipData(mv);
		return mv;
		
	}
	
	/**
	 * 订单编辑面板-加载配送方式
	 * @param request
	 * @param response
	 * @return
	 * @throws Exception
	 */
	public ModelAndView loadShippingMethod4EditPanel(HttpServletRequest request, HttpServletResponse response) throws Exception {
		ModelAndView mv = new ModelAndView("order/include/orderEditPanel4ShippingMethod");
		SalesOrder salesOrder = formBackingObject(request);
		mv.addObject("order", salesOrder);
		PaymentMethod paymentMethod = paymentMethodManager.getById(RequestUtil.getInteger(request, "paymentMethodId"));
		Integer regionId = RequestUtil.getInteger(request, "regionId");
		List<ShippingRate> shippingRateList = checkoutService.getRegionShippingRates(Constants.FLAG_TRUE.equals(paymentMethod.getIscod())?true:false, regionId);
		mv.addObject("shippingRateList", shippingRateList);
		return mv;
		
	}
	
	/**
	 * 订单编辑面板-加载支付与配送方式
	 * @param request
	 * @param response
	 * @return
	 * @throws Exception
	 */
	public ModelAndView loadPayShipMethodDiv4EditPanel(HttpServletRequest request, HttpServletResponse response) throws Exception {
		ModelAndView mv;
		SalesOrder salesOrder = formBackingObject(request);
		if(isProductRequired(request)){
			mv = new ModelAndView("order/include/orderEditPanel4PayAndShipMethodNeedProduct");
		}else{
			if(isShippingRequired(request)){
				mv = new ModelAndView("order/include/orderEditPanel4PayAndShipMethod");
				Integer regionId = RequestUtil.getInteger(request, "regionId");
				mv.addObject("regionId", regionId);
			}else{
				mv = new ModelAndView("order/include/orderEditPanel4PayAndVirtualShipMethod");
			}
		}
		mv.addObject("order", salesOrder);
		addPayAndShipData(mv);
		return mv;
		
	}
	/**
	 * 通过request传过来的信息获得是否需要先选择商品
	 * @param request
	 * @return
	 */
	public boolean isProductRequired(HttpServletRequest request){
		String[] productSkuCodes = RequestUtil.getParameterValuesNullSafe(request, "productSkuCodes");
		String[] giftCertAmts = RequestUtil.getParameterValuesNullSafe(request, "giftCertAmts");
		if(productSkuCodes.length == 0 && giftCertAmts.length == 0){
			return true;
		}else{
			return false;
		}
	}
	
	/**
	 * 通过request传过来的信息获得是否需要配送
	 * @return
	 */
	public boolean isShippingRequired(HttpServletRequest request){
		String[] productSkuCodes = RequestUtil.getParameterValuesNullSafe(request, "productSkuCodes");
		try{
			for(int i=0; i< productSkuCodes.length ; i++){
				ProductSku productSku = productSkuManager.getProductSkuByProductSkuCode(productSkuCodes[i]);
				if(productSku.getIsPhysicalProduct()){
					//只要其中一个是实体商品
					return true;
				}
			}
		}catch(Exception e){
			e.printStackTrace();
		}
		return false;
		
	}
	
	/**
	 * 订单编辑面板-加载自提方式
	 * @param request
	 * @param response
	 * @return
	 * @throws Exception
	 */
	public ModelAndView loadSelfCollectionCentre4EditPanel(HttpServletRequest request, HttpServletResponse response) throws Exception {
		ModelAndView mv = new ModelAndView("order/include/orderEditPanel4SelfCollectionCentre");
		SalesOrder salesOrder = formBackingObject(request);
		mv.addObject("order", salesOrder);
		Integer regionId = RequestUtil.getInteger(request, "regionId");
		List<SelfCollectionCentre> selfCollectionCentreList =  selfCollectionCentreManager.getSelfCollectionCentreListByRegionId(regionId);
		mv.addObject("selfCollectionCentreList", selfCollectionCentreList);
		return mv;
		
	}
	
	/**
	 * 订单修改：面板的地区修改
	 * @param request
	 * @param response
	 * @return
	 */
	public ModelAndView renderEditPanelRegionModify(HttpServletRequest request, HttpServletResponse response){
		ModelAndView mv = new ModelAndView("order/include/orderEditPanel4RegionModify");
		Integer regionId = RequestUtil.getInteger(request, "regionId");
		mv.addObject("regionId", regionId);
		return mv;
	}
	/**
	 * 订单修改：面板的地区县市
	 * @param request
	 * @param response
	 * @return
	 */
	public ModelAndView renderEditPanelRegionShow(HttpServletRequest request, HttpServletResponse response){
		ModelAndView mv = new ModelAndView("order/include/orderEditPanel4RegionShow");
		Integer regionId = RequestUtil.getInteger(request, "regionId");
		Region region = regionManager.getById(regionId);
		mv.addObject("regionId",regionId);
		mv.addObject("regionFullName",region.getFullName());
		return mv;
	}
	
	
	
	/**
	 * 订单修改预览面板  
	 * 原理：与下订单一样
	 * @param request
	 * @param response
	 * @return
	 * @throws Exception
	 */
	public ModelAndView showEditPreviewPanel(HttpServletRequest request, HttpServletResponse response) throws Exception {
		SalesOrder salesOrder = formBackingObject(request);
		ModelAndView mv = new ModelAndView("order/orderEditPanel4Preview");
		CheckoutSession checkoutSession = orderProcessFlowManager.buildCheckoutSession4Admin(request);
		mv.addObject("checkoutSession", checkoutSession);
		//----start:修改订单修改后的加减价部分
		if(null != salesOrder.getPremium()){
			checkoutSession.setPremiumMock(salesOrder.getPremium());
			checkoutSession.setTotalMock(checkoutSession.getTotal().add(checkoutSession.getPaidTotal()).add(salesOrder.getPremium()));
			
		}
		//----end:修改订单修改后的加减价部分
		mv.addObject("order", salesOrder);
		return mv;
	}
	
	/**
	 * 后台保存订单
	 * @param request
	 * @param response
	 * @return
	 * @throws Exception
	 */
	public ModelAndView saveOrder(HttpServletRequest request, HttpServletResponse response) throws Exception {
		Map<String, Object> data = new HashMap<String, Object>();
		SalesOrder salesOrder = formBackingObject(request);
		this.bind(request, salesOrder); //绑定金额
		try {
			CheckoutSession checkoutSession = orderProcessFlowManager.buildCheckoutSession4Admin(request);
			checkoutService.doEditOrder(salesOrder,checkoutSession); //特别注意
		}  catch (RuntimeException e) {
			data.put("error", e.getMessage());
			e.printStackTrace();
		}
		data.put("orderNo", salesOrder.getOrderNo());
		data.put("salesOrderId", salesOrder.getSalesOrderId());
		return getModelAndAjaxJsonView(data);
	}
	

	/**
	 * 应用标签
	 * 
	 * @param request
	 * @param response
	 * @return
	 * @throws Exception
	 */
	public ModelAndView applyTags(HttpServletRequest request, HttpServletResponse response) throws Exception {
		Map<String, Object> data = null;
		String tagNames = RequestUtil.getParameterNullSafe(request, "tagNames");
		String[] ids = request.getParameterValues("multiIds");
		if (ids != null && ids.length > 0) {
			for (String entityId : ids) {
				SalesOrder salesOrder = salesOrderManager.getById(Integer.valueOf(entityId));
				data = tagManager.doSetTagField(salesOrder, Tag.MODULE_ORDER, tagNames);
				salesOrderManager.save(salesOrder);
			}
		}
		return getModelAndAjaxJsonView(data);
	}

	
}
